#pragma once
#include"sock.h"
#include<poll.h>

namespace ns_server
{
    using namespace ns_sock;
    static u_int16_t g_default=8080;    //默认端口号
#define NUM 1024
    class Poll_Server
    {
    private:
        u_int16_t port_;
        int listen_sock_;
        struct pollfd fds_[NUM];
    public:
        Poll_Server(const u_int16_t& port=g_default):port_(port),listen_sock_(-1)
        {
            //初始化数组
            for(int i=0;i<NUM;i++)
            {
                fds_[i].fd=-1;
                fds_[i].events=0;
                fds_[i].revents=0;
            }
        }
        void InitServer()
        {
            listen_sock_=Sock::Socket();
            Sock::Bind(listen_sock_,port_);
            Sock::Listen(listen_sock_);
        }
        void PrintFds()
        {
            for(int i=0;i<NUM;i++)
            {
                if(fds_[i].fd==-1)
                    continue;
                std::cout<<fds_[i].fd<<" ";
            }
            std::cout<<std::endl;
        }
        void Loop()
        {
            //listen_sock添加进数组中
            fds_[0].fd=listen_sock_;
            fds_[0].events=POLLIN;
            int timeout=-1;    //-1为阻塞，>0为等待多少时间，=0为不等待，看一瞬有没数据就绪
            while(true)
            {
                PrintFds();
                int n=poll(fds_,NUM,timeout);
                switch(n)
                {
                    case 0:
                        std::cout<<"time out"<<std::endl;
                        break;
                    case -1:
                        std::cerr<<"poll error"<<std::endl;
                        break;
                    default:
                        HandlerEvent();   //处理数据
                        break;
                }
            }
        }
        //处理数据就绪的函数
        void HandlerEvent()
        {
            for(int i=0;i<NUM;i++)
            {
                if(fds_[i].fd==-1)
                    continue;
                if(fds_[i].revents==POLLIN)
                {
                    //std::cout<<"进入处理数据"<<std::endl;
                    //表示有数据就绪
                    if(fds_[i].fd==listen_sock_)
                    {
                        //代表有链接到来，就绪
                        sockaddr_in per;
                        socklen_t len=sizeof(per);
                        int sock=accept(listen_sock_,(sockaddr*)&per,&len);
                        //std::cout<<"accept sock "<<sock<<std::endl;
                        if(sock<0)
                        {
                            std::cerr<<"accept error"<<std::endl;
                            continue;
                        }
                        //把sock添加到数组中
                        int j=0;
                        for(;j<NUM;j++)
                        {
                            if(fds_[j].fd==-1)
                                break;
                        }
                        if(j==NUM)
                        {
                            //扩容
                            close(sock);  //不实现扩容装不下就丢弃
                        }
                        else
                        {
                            fds_[j].fd=sock;
                            fds_[j].events=POLLIN;
                            fds_[j].revents=0;
                        }
                    }
                    else
                    {
                        //代表其他文件数据就绪
                        char buffer[1024];
                        buffer[0]=0;   //不考虑粘包问题
                        int s=read(fds_[i].fd,buffer,sizeof(buffer));
                        switch(s)
                        {
                            case -1:
                                std::cerr<<"read error"<<std::endl;
                                break;
                            case 0:
                                std::cout<<"client quit"<<std::endl;
                                close(fds_[i].fd);
                                //从数组中剔除
                                fds_[i].fd=-1;
                                fds_[i].events=0;
                                fds_[i].revents=0;
                                break;
                            default:
                                buffer[s-1]=0;
                                std::cout<<"client say: "<<buffer<<std::endl;
                                break;
                        }
                    }
                }
            }
        }
        ~Poll_Server()
        {
            if(listen_sock_>0)
                close(listen_sock_);
        }
    };
}
